package com.smartleanx.module.hrm.service.esign.auth.impl;


import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.smartleanx.framework.security.core.util.SecurityFrameworkUtils;
import com.smartleanx.module.hrm.dal.dataobject.employee.EmployeeDO;
import com.smartleanx.module.hrm.dal.dataobject.esign.EsignPsnInfo;
import com.smartleanx.module.hrm.dal.mysql.employee.EmployeeMapper;
import com.smartleanx.module.hrm.dal.mysql.esign.EsignPsnInfoMapper;
import com.smartleanx.module.hrm.service.esign.auth.IPsnAuthService;
import com.smartleanx.module.hrm.service.esign.bo.PsnAuthBo;
import com.smartleanx.module.hrm.service.esign.temp.vo.Auth.EsignProperties;
import com.smartleanx.module.hrm.service.esign.temp.vo.Auth.PsnAuthResp;
import com.smartleanx.module.hrm.service.esign.temp.vo.Auth.PsnAuthVo;
import com.smartleanx.module.hrm.service.examine.util.exception.EsignException;
import com.smartleanx.module.hrm.service.examine.util.exception.ResultException;
import com.smartleanx.module.hrm.util.esign.constant.PsnAuthScope;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.security.PermitAll;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.smartleanx.module.hrm.util.esign.DesensitizationUtils.*;
import static com.smartleanx.module.hrm.util.esign.constant.PsnAuthScope.PSN_COMMON_SCOPE;

/**
 * @author yanglihao
 */

@Service
@AllArgsConstructor
@Slf4j
public class PsnAuthServiceImpl implements IPsnAuthService {

    private EsignProperties esignProperties;

//    private ICommonCheckService commonCheckService;

    private ESignAuthServiceImpl esignAuthService;

    private EmployeeMapper employeeMapper;

    private EsignPsnInfoMapper psnInfoMapper;

    @Override
    @PermitAll
    public PsnAuthVo getPsnAuthResult(PsnAuthBo param) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeDO employee = employeeMapper.selectByUserId(loginUserId);
        if (ObjectUtils.isEmpty(employee)) {
            throw new ResultException("此账号无法个人认证，请更换账号重试");
        }
        employee.setEsignAuthorizedStatusWeb(0);
        employeeMapper.updateById(employee);
        // 请求类型
        String requestType = param.getRequestType();
        param.setEmployeeId(employee.getId());
        // 当前员工
//        EmployeeDO employee = employeeMapper.selectOne(new LambdaUpdateWrapper<EmployeeDO>(){{
//            eq(EmployeeDO::getUserId,param.getEmployeeId());
//        }});
        // 查询
        if ("query".equalsIgnoreCase(requestType)) {
            return handlePsnQuery(employee);
        }
        // 认证
        if ("identity".equalsIgnoreCase(requestType)) {
            return handlePsnIdentity(employee, param);
        }
        // 授权
        if ("authorize".equalsIgnoreCase(requestType)) {
            return handlePsnAuthorize(employee, param);
        }
        log.error("未匹配到对应的业务方法，requestBody={}", param);
        throw new ResultException("操作失败");
    }

    @Override
    public Integer getStatus() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeDO employee = employeeMapper.selectByUserId(loginUserId);
        if (ObjectUtils.isEmpty(employee)) {
            return 0;
        }
        return employee.getEsignAuthorizedStatusWeb();
    }

    private PsnAuthVo handlePsnQuery(EmployeeDO employee) {

        // 已认证
        if (employee.getEsignRealnameStatus() == 1 && !ObjectUtils.isEmpty(employee.getEsignPsnId())) {
            EsignPsnInfo esignPsnInfo = psnInfoMapper.selectById(employee.getEsignPsnId());
            if (esignPsnInfo == null) {
                throw new ResultException("查询实名信息失败");
            }
            PsnAuthVo result = new PsnAuthVo();
            result.setPageType("info");
            result.setEmployeeId(employee.getId());
            // 认证信息
            result.setPsnRealnameStatus(1);
            result.setPsnAccount(desensitizePhone(esignPsnInfo.getPsnAccount()));
            result.setPsnName(desensitizeName(esignPsnInfo.getPsnName()));
            result.setPsnIdCardNum(desensitizeIdNumber(esignPsnInfo.getPsnIdCardNum()));
            // 授权信息
            result.setPsnAuthorizedStatus(employee.getEsignAuthorizedStatus());
            if (employee.getEsignAuthorizedStatus() == 1) {
                List<String> authorizedInfo = Arrays.stream(esignPsnInfo.getPsnAuthorizedInfo().split(","))
                        .map(String::trim).filter(code -> !code.isEmpty())
                        .map(code -> PsnAuthScope.PSN_AUTH_SCOPE_NAME.getOrDefault(code.toLowerCase(), "--"))
                        .collect(Collectors.toList());
                result.setPsnAuthorizedInfo(authorizedInfo);
            }
            return result;
        }
        // 未认证
        else {
            return PsnAuthVo.builder().pageType("input").employeeId(employee.getId()).build();
        }
    }

    private PsnAuthVo handlePsnIdentity(EmployeeDO employee, PsnAuthBo param) {
        try {
            PsnAuthResp authResp = esignAuthService.getPsnAuthUrl(param.getPsnAccount(), param.getPsnName(),
                    param.getPsnIdCardNum(), param.getRedirectUrl());

            // 更新实名授权流程ID
            employeeMapper.update(null, new LambdaUpdateWrapper<EmployeeDO>() {
                {
                    eq(EmployeeDO::getId, employee.getId());
                    set(EmployeeDO::getEsignAuthFlowId, authResp.getAuthFlowId());
                }
            });

            return PsnAuthVo.builder().pageType("toAuth").authUrl(authResp.getAuthUrl()).build();
        } catch (EsignException e) {
            log.error("获取认证/授权地址失败，requestBody={}，msg = {}", param, e.getMessage());
            throw new ResultException("操作失败，请联系管理员");
        }
    }

    private PsnAuthVo handlePsnAuthorize(EmployeeDO employee, PsnAuthBo param) {
        try {
//            String callbackUrl = esignProperties.getAuthCallbackUrl() + LoginInfoHolder.getTenantId();
            PsnAuthResp authResp = esignAuthService.getPsnAuthUrl(employee.getEsignPsnId(), PSN_COMMON_SCOPE,
                    param.getRedirectUrl());

            // 更新实名授权流程ID
            employeeMapper.update(null, new LambdaUpdateWrapper<EmployeeDO>() {
                {
                    eq(EmployeeDO::getId, employee.getId());
                    set(EmployeeDO::getEsignAuthFlowId, authResp.getAuthFlowId());
                }
            });
            return PsnAuthVo.builder().pageType("toAuth").authUrl(authResp.getAuthUrl()).build();
        } catch (EsignException e) {
            log.error("获取认证/授权地址失败，requestBody={}，msg = {}", param, e.getMessage());
            throw new ResultException("操作失败，请联系管理员");
        }
    }
}
